﻿using BLL;
using HslCommunication.MQTT;
using HslCommunication.Profinet.Melsec.Helper;
using Model;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using Newtonsoft.Json;
using PLCDataCollector.Core.Entities;
using PLCDataCollector.Core.Interfaces;
using PLCDataCollector.Core.Models;
using PLCDataCollector.Services;
using PLCDataCollector.Services.Data;
using PLCDataCollector.Services.PLC;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ListView;

namespace MachineStatusClient
{
    public partial class XFUserControl : UserControl
    {
        BContentToSqlServer bts = new BContentToSqlServer();
        private string time;
        private static string MqttIp = "192.168.190.21";
        private static int MqttPort = 6001;
        private static string MqttTopic = "ZXJDJData";

        private readonly IDataService _dataService;
        private List<DeviceMapping> _deviceMappings;
        private Dictionary<string, IPLCService> _plcServices;
        private Dictionary<string, Thread> _collectionThreads;
        public event Action<string, int, int, int> CriticalDataUpdated;
        private string machineId = ConfigurationManager.AppSettings["MachineId"];

        private bool IsStop = false;//下发暂停

        // MQTT 客户端
        private static IMqttClient _mqttClient;
        public XFUserControl()
        {
            InitializeComponent();
            dataGridView3.CellDoubleClick += dataGridView3_CellContentClick;

            _plcServices = new Dictionary<string, IPLCService>();
            _collectionThreads = new Dictionary<string, Thread>();
            // 读取配置
            var connectionString = ConfigurationManager.ConnectionStrings["SqlConnectionString"].ConnectionString.ToString(); ;

            // 创建数据服务实例
            _dataService = new DataService(connectionString);
            //txtUser.Enter += Control_Enter;
        }


        /// <summary>
        /// 新增点检记录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void buttonInsertDJ_Click(object sender, EventArgs e)
        {
            using (AddForm addForm = new AddForm())
            {
                if (addForm.ShowDialog() == DialogResult.OK)
                {
                    // 这里可以添加数据刷新逻辑（可选）
                    //BindWorkOrdersToDataGridView();
                    //BindWorkOrdersToDataGridView(new SearchModel
                    //{
                    //    StartTime = dateTimePickerStart.Value,
                    //    EndTime = DateTime.Now,
                    //    CZRY = "" //textBoxCZRY.Text.Trim()
                    //});
                    //MessageBox.Show("新增成功！");
                    //执行MQTT去同步点检记录到服务器
                    await SetupMqttClient();
                }
            }
        }

        private async Task SetupMqttClient()
        {
            try
            {
                _mqttClient = new MqttFactory().CreateMqttClient();
                MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder()
                       .WithClientId("CNC-SYS")
                       .WithCommunicationTimeout(TimeSpan.FromMilliseconds(50000))
                       .WithTcpServer(MqttIp, MqttPort);
                //if (ck_UserPwd.Checked)
                //{
                builder.WithCredentials("SYS", "1");
                //}
                IMqttClientOptions option = builder.Build();
                await _mqttClient.ConnectAsync(option);
                //Console.WriteLine(MqttIp + "MQTT 连接成功");
                ProcessData();//查询数据并同步
            }
            catch (Exception ex)
            {
                //Console.WriteLine($"MQTT 连接失败");
            }

        }

        private async void ProcessData()
        {
            try
            {
                // 1. 查询数据
                var data = FetchData();
                if (data.Count == 0)
                {
                    //Console.WriteLine($"{DateTime.Now}: 无新数据");
                    return;
                }

                // 2. MQTT 推送
                // Console.WriteLine($"{DateTime.Now}: 查询到 {data.Count} 条数据，开始推送...");
                var isPushSuccess = await PublishData(data);

                if (isPushSuccess)
                {
                    // 3. 修改迁移数据
                    UpdateData(data);
                    //Console.WriteLine($"{DateTime.Now}: 数据迁移删除完成");
                }
                else
                {
                    // Console.WriteLine($"{DateTime.Now}: MQTT 推送失败，数据保留");
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine($"{DateTime.Now}: 处理失败 - {ex.Message}");
            }
        }

        private List<ZXJDataModel> FetchData()
        {
            var data = new List<ZXJDataModel>();
            var dt = bts.GetDJData();
            if (dt != null && dt.Count > 0)
            {
                foreach (var item in dt)
                {
                    data.Add(new ZXJDataModel
                    {
                        MachineId = item.MachineId,
                        JJTZKG = item.JJTZKG,
                        JSQ = item.JSQ,
                        RJJM = item.RJJM,
                        XJTX = item.XJTX,
                        FGJP = item.FGJP,
                        ZDMD = item.ZDMD,
                        THJC = item.THJC,
                        BTHJC = item.BTHJC,
                        THZZ = item.THZZ,
                        JZQG = item.JZQG,
                        AQMZZ = item.AQMZZ,
                        JTBMZW = item.JTBMZW,
                        GQGYZZ = item.GQGYZZ,
                        JTSFLQ = item.JTSFLQ,
                        QYB = item.QYB,
                        YSKQ = item.YSKQ,
                        DZDJ = item.DZDJ,
                        SDZH = item.SDZH,
                        XRHBW = item.XRHBW,
                        ZDP = item.ZDP,
                        TRCDBF = item.TRCDBF,
                        PD = item.PD,
                        LDJC = item.LDJC,
                        CZRY = item.CZRY,
                        ZZ = item.ZZ,
                        JXBQ = item.JXBQ,
                        GetTime = Convert.ToDateTime(item.GetTime),
                        DJDate = Convert.ToDateTime(item.DJDate),
                        DJType = item.DJType,
                        ID = item.ID
                    });
                }
            }


            return data;
        }
        /// <summary>
        /// 修改同步的数据
        /// </summary>
        /// <param name="data"></param>
        private void UpdateData(List<ZXJDataModel> data)
        {
            List<string> idList = data.Where(d => !string.IsNullOrEmpty(d.ID))
                         .Select(d => d.ID)
                         .ToList();

            // 执行批量修改
            int updatedRows = bts.UpdateData(idList);
        }

        private static async Task<bool> PublishData(List<ZXJDataModel> data)
        {
            try
            {
                var payload = JsonConvert.SerializeObject(data);
                var message = new MqttApplicationMessageBuilder()
                    .WithTopic(MqttTopic)
                    .WithPayload(payload)
                    .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce)
                    .Build();

                var result = await _mqttClient.PublishAsync(message);
                return result.ReasonCode == MQTTnet.Client.Publishing.MqttClientPublishReasonCode.Success;
            }
            catch
            {
                return false;
            }
        }

        private void BindWorkOrdersToDataGridView(SearchModel searchCondition = null)
        {
            try
            {
                // 1. 从配置读取设备编码
                //string machineId = ConfigurationManager.AppSettings["DeviceCode"];
                dataGridView3.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
                dataGridView3.ColumnHeadersHeight = 45;
                //if (string.IsNullOrEmpty(machineId))
                //{
                //    MessageBox.Show("设备编码未配置！");
                //    return;
                //}
                // 使用传入的查询条件（如果为空则创建默认条件）
                var condition = searchCondition ?? new SearchModel();
                // 2. 调用接口获取数据
                List<DJDayDataModelList> workOrders = bts.GetDayDJList(condition);

                // 3. 绑定到DataGridView
                if (workOrders != null && workOrders.Count > 0)
                {
                    // 绑定数据源
                    dataGridView3.DataSource = workOrders;
                    dataGridView3.RowTemplate.Height = 45;
                    // 配置列映射（字段名 -> 列名）
                    //dataGridView1.AutoGenerateColumns = false; // 禁止自动生成列
                    // 设置开始时间和结束时间列的格式
                    //if (dataGridView3.Columns.Contains("Column5"))
                    //{
                    //    dataGridView3.Columns["Column5"].DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss";
                    //    dataGridView3.Columns["Column5"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                    //}
                    if (dataGridView3.Columns.Contains("Column3"))
                    {
                        dataGridView3.Columns["Column3"].DefaultCellStyle.Format = "yyyy-MM-dd";
                        dataGridView3.Columns["Column3"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                        // 确保使用格式提供程序（关键）
                        //dataGridView3.Columns["Column3"].DefaultCellStyle.FormatProvider = CultureInfo.InvariantCulture;
                    }
                    // 强制刷新显示（可选）
                    //dataGridView3.Refresh();


                    //Message.Text = "";
                }
                else
                {
                    //MessageBox.Show("未查询到工单数据");
                    //Message.Text = "未查询到工单排程数据";
                    //Message.ForeColor = Color.Red;
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show($"加载数据失败: {ex.Message}");
                //Message.Text = $"加载数据失败: {ex.Message}";
                //Message.ForeColor = Color.Red;
            }
        }

        private void dataGridView3_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            // 忽略标题行和无效点击
            if (e.RowIndex < 0 || e.ColumnIndex < 0) return;

            // 获取"时间"列的值（假设列名为"时间"）
            string timeValue = dataGridView3.Rows[e.RowIndex].Cells["Column4"].Value?.ToString();

            if (!string.IsNullOrEmpty(timeValue))
            {
                time = timeValue;  // 存储时间值
                OpenAddForm();          // 跳转到新窗体
                //DJSearchForm searchForm = new DJSearchForm();
                //searchForm.ShowDialog(this);
            }
            else
            {
                MessageBox.Show("时间数据为空，无法跳转");
            }
        }

        private void OpenAddForm()
        {
            // 1. 创建承载窗体
            //Form hostForm = new Form();
            //hostForm.Text = "工单详情";  // 设置窗体标题
            //hostForm.Size = new Size(1650, 650);
            //hostForm.StartPosition = FormStartPosition.CenterScreen;  // 关键居中设置

            // 2. 实例化用户控件
            DJSearchForm searchForm = new DJSearchForm();
            searchForm.Size = new Size(1650, 650);

            // 3. 传递工单号到用户控件（需在DJAddUserControl中添加接收方法）
            searchForm.SetMachineId(time);

            // 4. 设置用户控件填充窗体
            //dJAddUserControl.Dock = DockStyle.Fill;

            // 5. 将控件添加到窗体
            //hostForm.Controls.Add(dJAddUserControl);

            // 6. 显示窗体
            //hostForm.Show();
            searchForm.ShowDialog(this);
            //DJAddUserControl dJAddUserControl = new DJAddUserControl();
            //dJAddUserControl.Show();
        }

        // 添加Windows API导入
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        // 其他现有代码...

        // 添加显示屏幕键盘的方法
        private void ShowOnScreenKeyboard()
        {
            try
            {
                // 检查屏幕键盘是否已经在运行
                var oskProcess = Process.GetProcessesByName("osk").FirstOrDefault();

                if (oskProcess == null)
                {
                    // 启动屏幕键盘
                    Process.Start("osk.exe");
                }
                else
                {
                    // 如果已经在运行，将其带到前台
                    SetForegroundWindow(oskProcess.MainWindowHandle);
                }
            }
            catch (Exception ex)
            {
                // 如果无法启动屏幕键盘，可以尝试其他方法
                try
                {
                    // 尝试使用tabtip (Windows 10触摸键盘)
                    Process.Start("tabtip.exe");
                }
                catch
                {
                    MessageBox.Show("无法启动屏幕键盘: " + ex.Message);
                }
            }
        }

        // 添加Enter事件处理程序
        private void Control_Enter(object sender, EventArgs e)
        {
            ShowOnScreenKeyboard();
        }

        private void btnXF_Click(object sender, EventArgs e)
        {
            StopAllCollectionThreads();


            _deviceMappings = _dataService.GetDeviceMappings(machineId);
            var list = new List<PlcWriteModel>();
            //ZB39
            list.Add(new PlcWriteModel() { Plc = "ZB39-Machine002", DataAddress = "D218", DataValue = 5050 });
            list.Add(new PlcWriteModel() { Plc = "ZB39-Machine001", DataAddress = "D218", DataValue = 2 });
            list.Add(new PlcWriteModel() { Plc = "ZB39-Machine001", DataAddress = "D220", DataValue = 200 });

            //i41射出
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D870", DataValue = 2050 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D871", DataValue = 2050 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D872", DataValue = 701 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D873", DataValue = 701 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D874", DataValue = 601 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "W100.00", DataValue = 1 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "W100.00", DataValue = 0 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D55", DataValue = 1 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D160", DataValue = 256 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine001", DataAddress = "D61", DataValue = 39312 });
            //i41铁壳
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine002", DataAddress = "D4200", DataValue = 4 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine002", DataAddress = "D4204", DataValue = 2 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine002", DataAddress = "D20", DataValue = 12 });
            //list.Add(new PlcWriteModel() { Plc = "I41-Machine002", DataAddress = "M520", DataValue = 0 ,DataType="BOOL"});
            foreach (var item in list)
            {
                var result = _plcServices[item.Plc].WriteData(item);
            }


            //InitializePlcConnections();
        }

        private void XFUserControl_Load(object sender, EventArgs e)
        {
            InitializePlcConnections();
        }
        private void InitializePlcConnections()
        {
            try
            {
                // 获取设备映射
                var machineId = ConfigurationManager.AppSettings["MachineId"];
                _deviceMappings = _dataService.GetDeviceMappings(machineId);

                // 创建PLC服务
                foreach (var device in _deviceMappings)
                {
                    var service = PLCServiceFactory.CreatePLCService(device);
                    if (service.Connect())
                    {
                        _plcServices.Add(device.MmachineId + "-" + device.MachineId, service);

                        var thread = new Thread(() => DeviceDataCollectionWorker(device));
                        thread.Name = $"DataCollection_{device.MachineId}";
                        thread.IsBackground = true;

                        _collectionThreads.Add(device.MmachineId + "-" + device.MachineId, thread);
                        thread.Start();
                        //Log($"成功连接到设备: {device.MachineId}, IP: {device.Ip}");
                    }
                    else
                    {
                        // Log($"连接设备失败: {device.MachineId}, IP: {device.Ip}");
                    }
                }
            }
            catch (Exception ex)
            {
                // 处理异常
            }
        }
        private void DeviceDataCollectionWorker(DeviceMapping device)
        {
            var dataBuffer = new List<PlcDataHistory>();
            var lastSaveTime = DateTime.Now;

            // 获取所有点位详情
            var details = _dataService.GetList(device.MmachineId, device.MachineId, 0, 1000);

            // 筛选出四个关键点位（D1, D2, D3, D4）
            var criticalDetails = details.Where(d =>
                d.DataAddress == "D1" ||
                d.DataAddress == "D2" ||
                d.DataAddress == "D3").ToList();

            // 其他点位
            var otherDetails = details.Except(criticalDetails).ToList();

            while (!IsStop)
            {
                try
                {
                    foreach (var detail in otherDetails)
                    {
                        var serviceKey = device.MmachineId + "-" + device.MachineId;
                        if (_plcServices.ContainsKey(serviceKey))
                        {
                            var result = _plcServices[serviceKey].ReadData(detail);
                            if (result.IsSuccess)
                            {
                                // 保存到数据缓冲区
                                lock (dataBuffer)
                                {
                                    dataBuffer.Add(new PlcDataHistory
                                    {
                                        MachineId = device.MachineId,
                                        DataAddress = detail.DataAddress,
                                        DataName = detail.DataName,
                                        DataValue = result.Content.ToString(),
                                        DataType = detail.DataType,
                                        MMachineId = device.MmachineId,
                                        CollectionTime = DateTime.Now
                                    });
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    // 处理异常
                }

                // 批量保存所有数据
                if (dataBuffer.Count > 0)
                {
                    _dataService.BatchSavePlcData(dataBuffer);
                    dataBuffer.Clear();
                }
                lastSaveTime = DateTime.Now;

                Thread.Sleep(500);
            }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }

            // 停止线程
            StopAllCollectionThreads();

            base.Dispose(disposing);
        }
        /// <summary>
        /// 停止所有数据采集线程
        /// </summary>
        public void StopAllCollectionThreads()
        {
            IsStop = true; // 设置停止标志

            // 等待所有线程结束
            foreach (var thread in _collectionThreads.Values)
            {
                if (thread != null && thread.IsAlive)
                {
                    // 等待线程终止（设置超时时间避免无限等待）
                    if (!thread.Join(3000)) // 5秒超时
                    {
                        // 超时后强制中止（尽量避免使用，仅作为最后的手段）
                        thread.Abort();
                    }
                }
            }

            // 断开所有PLC连接
            foreach (var service in _plcServices.Values)
            {
                if (service.IsConnected)
                {
                    service.Disconnect();
                }
            }

            // 清空线程字典
            _collectionThreads.Clear();
            _plcServices.Clear();
        }

        private void bynSync_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.txtWorkNo.Text.Trim()))
            {
                MessageBox.Show("请扫描工单号!");
                return;
            }
            var results = _dataService.ExecuteLinkedStoredProcedure<GetInfoModel>(
            "192.168.190.21",
            "IotData",
            "DCS_SCJ_SP",
            new SugarParameter("@MachineNo", machineId),
            new SugarParameter("@WorkNo", this.txtWorkNo.Text.Trim()),
            new SugarParameter("@callType", 1)
            );
            var results1 = _dataService.ExecuteLinkedStoredProcedure<GetDetailInfoModel>(
            "192.168.190.21",
            "IotData",
            "DCS_SCJ_SP",
            new SugarParameter("@MachineNo", machineId),
            new SugarParameter("@WorkNo", this.txtWorkNo.Text.Trim()),
            new SugarParameter("@callType", 2)
            );
            //检查是否有后台线程在使用，有则移除
            if (_plcServices.Any())
            {
                StopAllCollectionThreads();
            }
            //移除完成后,将最新获取的内容填充至本地数据库
            var str = _dataService.ChangeInfo(machineId, results, results1);

            //先下发参数
            _deviceMappings = _dataService.GetDeviceMappings(machineId);
            // 创建PLC服务
            foreach (var device in _deviceMappings)
            {
                
                var service = PLCServiceFactory.CreatePLCService(device);
                if (service.Connect())
                {
                    var key = device.MmachineId + "-" + device.MachineId;
                    if (!_plcServices.ContainsKey(key))
                    {
                        _plcServices.Add(key, service);
                    }

                    var details = results1.Where(x => (x.Type == 1 || x.Type == 2) && x.MachineId.Trim() == device.MachineId && x.MmachineId.Trim() == device.MmachineId).Select(x => new PlcWriteModel
                    {
                        DataAddress = x.DataAddress,
                        DataType = x.DataType,
                        DataValue = x.DataValue,
                        Plc = $"{x.MmachineId.Trim()}-{x.MachineId}"
                    });
                    //var details = new List<PlcWriteModel>();
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D870", DataValue = 2050, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D871", DataValue = 2050, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D872", DataValue = 701, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D873", DataValue = 701, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D874", DataValue = 601, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D55", DataValue = 1, DataType = "int16" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D160", DataValue = 256, DataType = "int32" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "D61", DataValue = 39312, DataType = "int32" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "W100.00", DataValue = 1, DataType = "bool" });
                    //details.Add(new PlcWriteModel() { Plc = "I41-SCJ_01", DataAddress = "W100.00", DataValue = 0, DataType = "bool" });
                    foreach (var item in details)
                    {
                        _plcServices[key].WriteData(item);
                        Thread.Sleep(500);
                    }

                    var thread = new Thread(() => DeviceDataCollectionWorker(device));
                    thread.Name = $"DataCollection_{device.MmachineId}_{device.MachineId}";
                    thread.IsBackground = true;
                    if (!_collectionThreads.ContainsKey(key))
                    {
                        _collectionThreads.Add(key, thread);
                    }

                    IsStop = false;
                    thread.Start();
                    //Log($"成功连接到设备: {device.MachineId}, IP: {device.Ip}");
                }
                else
                {
                    // Log($"连接设备失败: {device.MachineId}, IP: {device.Ip}");
                    MessageBox.Show($"连接失败:" + device.Ip);
                }
            }
            MessageBox.Show("下发成功");
            //this.label3.Text = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}下发成功";
            //this.label3.ForeColor = Color.Red;
        }
    }

}
